package wo.jpa.reader.entity;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Table;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import wo.common.util.WoUtil;
import wo.jpa.reader.util.JPAReaderUtil;

public class WoJPAField {
	
	private final static Logger LOG = LogManager.getLogger(WoJPAField.class);
	
	public WoJPAField (Field f, Table t) {
		Column c = f.getDeclaredAnnotation(Column.class);
		this.fieldName = f.getName();
		this.fieldType = f.getType();
		if (c == null) {
			this.columnName = f.getName();
			this.table = t.name();
		} else {
			this.columnName = c.name();
			if (WoUtil.isEmpty(columnName)) {
				this.columnName = this.fieldName;
			}
			this.columnDefinition = c.columnDefinition();
			this.insertable = c.insertable();
			this.length = c.length();
			this.nullable = c.nullable();
			this.precision = c.precision();
			this.scale = c.scale();
			this.table = c.table();
			this.unique = c.unique();
			this.updatable = c.updatable();
		}
	}
	
	private String fieldName = "";
	
	/**
	 * 注释中的参数
	 */
	private Map<String, String> params = new HashMap<String, String>();
	
	/**
	 * 注释
	 */
	private String fieldComment = "";
	
	private Class fieldType;
	
	private WoJPAEntity entity;
	
	/**
     * (Optional) The name of the column. Defaults to
     * the property or field name.
     */
    private String columnName = "";

    /**
     * (Optional) Whether the column is a unique key.  This is a
     * shortcut for the <code>UniqueConstraint</code> annotation at the table
     * level and is useful for when the unique key constraint
     * corresponds to only a single column. This constraint applies
     * in addition to any constraint entailed by primary key mapping and
     * to constraints specified at the table level.
     */
    private boolean unique = false;

    /**
     * (Optional) Whether the database column is nullable.
     */
    private boolean nullable = true;

    /**
     * (Optional) Whether the column is included in SQL INSERT
     * statements generated by the persistence provider.
     */
    private boolean insertable = true;

    /**
     * (Optional) Whether the column is included in SQL UPDATE
     * statements generated by the persistence provider.
     */
    private boolean updatable = true;

    /**
     * (Optional) The SQL fragment that is used when
     * generating the DDL for the column.
     * <p> Defaults to the generated SQL to create a
     * column of the inferred type.
     */
    private String columnDefinition = "";

    /**
     * (Optional) The name of the table that contains the column.
     * If absent the column is assumed to be in the primary table.
     */
    private String table = "";

    /**
     * (Optional) The column length. (Applies only if a
     * string-valued column is used.)
     */
    private int length = 255;

    /**
     * (Optional) The precision for a decimal (exact numeric)
     * column. (Applies only if a decimal column is used.)
     * Value must be set by developer if used when generating
     * the DDL for the column.
     */
    private int precision = 0;

    /**
     * (Optional) The scale for a decimal (exact numeric) column.
     * (Applies only if a decimal column is used.)
     */
    private int scale = 0;

	public String getColumnName() {
		return columnName;
	}

	public void setColumnName(String columnName) {
		this.columnName = columnName;
	}

	public String getFieldName() {
		return fieldName;
	}
	
	public String getFieldNameUpperFirstChar() {
		return WoUtil.getUpperFirstChar(fieldName);
	}

	public void setFieldName(String fieldName) {
		this.fieldName = fieldName;
	}
	
	public String getFieldComment() {
		return fieldComment;
	}

	public void setFieldComment(String fieldComment) {
		this.fieldComment = fieldComment;
		this.params = JPAReaderUtil.getParamsInComment(fieldComment);
	}

	/**
	 * 从注释中获取中文名.
	 * @return
	 */
	public String getFieldCN() {
		return JPAReaderUtil.getNameInComment(fieldComment, fieldName);
	}
	
	public Class getFieldType() {
		return fieldType;
	}

	public void setFieldType(Class fieldType) {
		this.fieldType = fieldType;
	}

	public String getAlias () {
		if (this.columnName.equals(this.fieldName)) {
			return "";
		}
		return this.fieldName;
	}
	
	public boolean isUnique() {
		return unique;
	}

	public void setUnique(boolean unique) {
		this.unique = unique;
	}

	public boolean isNullable() {
		return nullable;
	}

	public void setNullable(boolean nullable) {
		this.nullable = nullable;
	}

	public boolean isInsertable() {
		return insertable;
	}

	public void setInsertable(boolean insertable) {
		this.insertable = insertable;
	}

	public boolean isUpdatable() {
		return updatable;
	}

	public void setUpdatable(boolean updatable) {
		this.updatable = updatable;
	}

	public String getColumnDefinition() {
		return columnDefinition;
	}

	public void setColumnDefinition(String columnDefinition) {
		this.columnDefinition = columnDefinition;
	}

	public String getTable() {
		return table;
	}

	public void setTable(String table) {
		this.table = table;
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public int getPrecision() {
		return precision;
	}

	public void setPrecision(int precision) {
		this.precision = precision;
	}

	public int getScale() {
		return scale;
	}

	public void setScale(int scale) {
		this.scale = scale;
	}

	public WoJPAEntity getEntity() {
		return entity;
	}

	public void setEntity(WoJPAEntity entity) {
		this.entity = entity;
	}
	
	public String getGetterName () {
    	return "get" + getFieldNameUpperFirstChar();
    }
    
    public String getSetterName () {
    	return "set" + getFieldNameUpperFirstChar();
    }
    
    public Boolean isOrderable () {
    	String param = params.get("排序");
    	if (param == null) {
    		return false;
    	}
    	return true;
    }
    
    public String getOrder () {
    	return params.get("排序");
    }
    
    /**
     * @return
     */
    public Boolean isRequired () {
    	if (!this.nullable) {
    		return true;
    	}
    	String param = params.get("必填");
    	if (WoUtil.isEmpty(param) || "否".equals(param)) {
    		return false;
    	}
    	return true;
    }
}
